home *** CD-ROM | disk | FTP | other *** search
- /*
- * pmap_check - additional portmap security.
- *
- * Always reject non-local requests to update the portmapper tables.
- *
- * Refuse to forward mount requests to the nfs mount daemon. Otherwise, the
- * requests would appear to come from the local system, and nfs export
- * restrictions could be bypassed.
- *
- * Refuse to forward requests to the nfsd process.
- *
- * Refuse to forward requests to NIS (YP) daemons; The only exception is the
- * YPPROC_DOMAIN_NONACK broadcast rpc call that is used to establish initial
- * contact with the NIS server.
- *
- * Always allocate an unprivileged port when forwarding a request.
- *
- * If compiled with -DCHECK_PORT, require that requests to register or
- * unregister a privileged port come from a privileged port. This makes it
- * more difficult to replace a critical service by a trojan.
- *
- * If compiled with -DHOSTS_ACCESS, reject requests from hosts that are not
- * authorized by the /etc/hosts.{allow,deny} files. The local system is
- * always treated as an authorized host. Access control is based on IP
- * addresses only; attempts to map an address to a host name might cause the
- * portmapper to hang.
- *
- * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
- * Computing Science, Eindhoven University of Technology, The Netherlands.
- */
-
- #ifndef lint
- static char sccsid[] = "@(#) pmap_check.c 1.2 92/07/06 19:53:32";
- #endif
-
- #include <rpc/rpc.h>
- #include <rpc/pmap_prot.h>
- #include <syslog.h>
- #include <netdb.h>
- #include <sys/signal.h>
- #ifdef SYSV40
- #include <netinet/in.h>
- #include <rpc/rpcent.h>
- #endif
-
- extern char *inet_ntoa();
-
- #include "pmap_check.h"
-
- /* Explicit #defines in case the include files are not available. */
-
- #define NFSPROG ((u_long) 100003)
- #define MOUNTPROG ((u_long) 100005)
- #define YPXPROG ((u_long) 100069)
- #define YPPROG ((u_long) 100004)
- #define YPPROC_DOMAIN_NONACK ((u_long) 2)
- #define MOUNTPROC_MNT ((u_long) 1)
-
- static void logit();
- static void toggle_verboselog();
- static int verboselog = 0;
-
- /* A handful of macros for "readability". */
-
- #define legal_host(a) \
- (from_local(a) || hosts_ctl("portmap", "", inet_ntoa(a->sin_addr), ""))
-
- #define legal_port(a,p) \
- (ntohs((a)->sin_port) < IPPORT_RESERVED || (p) >= IPPORT_RESERVED)
-
- #define log_bad_port(addr, proc, prog) \
- logit(LOG_ERR, addr, proc, prog, ": request from unprivileged port")
-
- #define log_bad_host(addr, proc, prog) \
- logit(LOG_ERR, addr, proc, prog, ": request from unauthorized host")
-
- #define log_bad_owner(addr, proc, prog) \
- logit(LOG_ERR, addr, proc, prog, ": request from non-local host")
-
- #define log_no_forward(addr, proc, prog) \
- logit(LOG_ERR, addr, proc, prog, ": request not forwarded")
-
- #define log_client(addr, proc, prog) \
- logit(LOG_INFO, addr, proc, prog, "")
-
- /* check_startup - additional startup code */
-
- void check_startup()
- {
-
- /*
- * Give up root privileges so that we can never allocate a privileged
- * port when forwarding an rpc request.
- */
- if (setuid(1) == -1) {
- syslog(LOG_ERR, "setuid(1) failed: %m");
- exit(1);
- }
- (void) signal(SIGINT, toggle_verboselog);
- }
-
- /* check_default - additional checks for NULL, DUMP, GETPORT and unknown */
-
- check_default(addr, proc, prog)
- struct sockaddr_in *addr;
- u_long proc;
- u_long prog;
- {
- #ifdef HOSTS_ACCESS
- if (!legal_host(addr)) {
- log_bad_host(addr, proc, prog);
- return (FALSE);
- }
- #endif
- if (verboselog)
- log_client(addr, proc, prog);
- return (TRUE);
- }
-
- /* check_privileged_port - additional checks for privileged-port updates */
-
- check_privileged_port(addr, proc, prog, port)
- struct sockaddr_in *addr;
- u_long proc;
- u_long prog;
- u_long port;
- {
- #ifdef CHECK_PORT
- if (!legal_port(addr, port)) {
- log_bad_port(addr, proc, prog);
- return (FALSE);
- }
- #endif
- return (TRUE);
- }
-
- /* check_setunset - additional checks for update requests */
-
- check_setunset(addr, proc, prog, port)
- struct sockaddr_in *addr;
- u_long proc;
- u_long prog;
- u_long port;
- {
- if (!from_local(addr)) {
- log_bad_owner(addr, proc, prog);
- return (FALSE);
- }
- if (port && !check_privileged_port(addr, proc, prog, port))
- return (FALSE);
- if (verboselog)
- log_client(addr, proc, prog);
- return (TRUE);
- }
-
- /* check_callit - additional checks for forwarded requests */
-
- check_callit(addr, proc, prog, aproc)
- struct sockaddr_in *addr;
- u_long proc;
- u_long prog;
- u_long aproc;
- {
- #ifdef HOSTS_ACCESS
- if (!legal_host(addr)) {
- log_bad_host(addr, proc, prog);
- return (FALSE);
- }
- #endif
- if (prog == PMAPPROG || prog == NFSPROG || prog == YPXPROG ||
- (prog == MOUNTPROG && aproc == MOUNTPROC_MNT) ||
- (prog == YPPROG && aproc != YPPROC_DOMAIN_NONACK)) {
- log_no_forward(addr, proc, prog);
- return (FALSE);
- }
- if (verboselog)
- log_client(addr, proc, prog);
- return (TRUE);
- }
-
- /* toggle_verboselog - toggle verbose logging flag */
-
- static void toggle_verboselog(sig)
- int sig;
- {
- (void) signal(sig, toggle_verboselog);
- verboselog = !verboselog;
- }
-
- /* logit - report events of interest via the syslog daemon */
-
- static void logit(severity, addr, procnum, prognum, text)
- int severity;
- struct sockaddr_in *addr;
- u_long procnum;
- u_long prognum;
- char *text;
- {
- char *procname;
- char procbuf[4 * sizeof(u_long)];
- char *progname;
- char progbuf[4 * sizeof(u_long)];
- struct rpcent *rpc;
- struct proc_map {
- u_long code;
- char *proc;
- };
- struct proc_map *procp;
- static struct proc_map procmap[] = {
- PMAPPROC_CALLIT, "callit",
- PMAPPROC_DUMP, "dump",
- PMAPPROC_GETPORT, "getport",
- PMAPPROC_NULL, "null",
- PMAPPROC_SET, "set",
- PMAPPROC_UNSET, "unset",
- 0, 0,
- };
-
- /*
- * Fork off a process or the portmap daemon might hang while
- * getrpcbynumber() or syslog() does its thing.
- */
-
- if (fork() == 0) {
-
- /* Try to map program number to name. */
-
- if (prognum == 0) {
- progname = "";
- } else if (rpc = getrpcbynumber((int) prognum)) {
- progname = rpc->r_name;
- } else {
- sprintf(progname = progbuf, "%lu", prognum);
- }
-
- /* Try to map procedure number to name. */
-
- for (procp = procmap; procp->proc && procp->code != procnum; procp++)
- /* void */ ;
- if ((procname = procp->proc) == 0)
- sprintf(procname = procbuf, "%lu", (u_long) procnum);
-
- /* Write syslog record. */
-
- syslog(severity, "connect from %s to %s(%s)%s",
- inet_ntoa(addr->sin_addr), procname, progname, text);
- exit(0);
- }
- }
-